package service

import (
	"encoding/json"
	"git.oschina.net/fanbuchi/redpack/conf/rsa"
	"git.oschina.net/fanbuchi/redpack/database"
	"git.oschina.net/fanbuchi/redpack/domain"
	"git.oschina.net/fanbuchi/redpack/errors"
	"github.com/google/uuid"
	"github.com/jinzhu/gorm"
	"golang.org/x/crypto/bcrypt"
	"time"
)

type OauthService struct {

}

func  (service*OauthService)Revoke(token string)(*domain.Oauth,error)  {
	if token=="" || len(token)==0 {
		 return nil,nil
	}
	 param:=domain.Oauth{AccessToken:token}
	oauthResult,err:=service.Query(&param)
	if err!=nil {
		return nil,err
	}
	return oauthResult,nil
}

func  (service*OauthService)Token(account *domain.Account)(*domain.Oauth,error)  {
	accountService:=new(AccountService)
	accountResult,err:=accountService.Query1ByUserName(account.UserName)
	if err!=nil {
		return nil,err
	}
	// 禁用账户
	if accountResult.DeletedAt!=nil{
		return nil,_error.ErrAccountEnable
	}
	//对比密码
	err=bcrypt.CompareHashAndPassword([]byte(accountResult.Password),[]byte(account.Password))
	if err!=nil {
		return nil,_error.ErrAccountPassword
	}
	//token 授权


	oauthResult:=new(domain.Oauth)
	err=database.Master().
		Where("account_id = ?", accountResult.ID).
		First(oauthResult).
		Error
	if err!=nil && err!=gorm.ErrRecordNotFound {
		return nil,err
	}
	oauthResult.UpdatedAt=time.Now()


	//accessToken:=uuid.New().String()
	refreshToken:=uuid.New().String()

	if oauthResult.ID<=0  {
		data,_:=json.Marshal(oauthResult)
		accessToken, err :=rsa.RsaEncryptBase64(data)
		if err!=nil {
			return nil,err
		}
		oauth:=domain.Oauth{AccountId:accountResult.ID,
			TokenType:"Bearer",
			AccessToken:accessToken,
			RefreshToken:refreshToken,
			Scope:accountResult.Role,
			ExpiresIn:7*24*60*60,
		}
		err=database.Master().Create(&oauth).Error
		if err!=nil {
			return nil,err
		}
		return &oauth,nil
	}else{
		oauthResult.Scope=accountResult.Role
		grant:=domain.Oauth{AccountId:oauthResult.AccountId,
			Scope:oauthResult.Scope,
		}
		grant.UpdatedAt=time.Now()
		data,_:=json.Marshal(grant)
		accessToken, err :=rsa.RsaEncryptBase64(data)
		if err!=nil {
			return nil,err
		}
		oauthResult.AccessToken=accessToken
		oauthResult.RefreshToken=refreshToken
		//部分更新
		err = database.Master().Model(&oauthResult).
			/*Select("access_token").
			Select("refresh_token").
			Select("role").*/
				Updates(map[string]interface{}{"access_token": accessToken,
					"refresh_token": refreshToken, "role": accountResult.Role}).Error
		if err!=nil  {
			return nil,err
		}
	}
	return oauthResult,nil
}
//退出登陆
func  (service*OauthService)Logout(oauth *domain.Oauth)(*domain.Oauth,error)  {
	err :=database.Master().
		Where("account_id = ?", oauth.AccountId).
		First(oauth).Error
	if err != nil {
		return nil,_error.ErrAccountNotExist
	}
	//affected
	 err = database.Master().Model(oauth).
		Updates(map[string]interface{}{
		"access_token": "",
		"refresh_token": "",
	}).Error

	if  err != nil  {
		return nil,err
	}
	return oauth,nil
}

func  (service*OauthService)Create(oauth *domain.Oauth)(*domain.Oauth,error)  {
	oauth.ID=0
	database.Master().
		Where("account_id = ?", oauth.AccountId).
		First(oauth)
	if oauth.ID!=0 {
		return nil,_error.ErrAccountExist
	}
	err:=database.Master().First(&oauth).Error
	if err != nil  {
		// 错误处理...
		return nil,err
	}
	return oauth,nil
}

func  (service*OauthService)Delete(oauth *domain.Oauth)(*domain.Oauth,error)   {
	err:=database.Master().Delete(&oauth).Error
	if err != nil  {
		// 错误处理...
		return nil,err
	}
	return oauth,nil
}

func  (service*OauthService)Update(oauth *domain.Oauth)(*domain.Oauth,error)      {
	err := database.Master().Update(oauth).Error
	if err != nil  {
		// 错误处理...
		return nil,err
	}
	return oauth,nil
}

func  (service*OauthService)Query(oauth *domain.Oauth)(*domain.Oauth,error)  {
	//oauthResult := make([]*domain.Oauth, 0)
	var ret domain.Oauth
	 err:=database.Master().Where(oauth).First(&ret).Error
	if err!=nil {
		return nil,err
	}
	return &ret,nil
}

func  (service*OauthService)QueryById(id int64)(*domain.Oauth,error)  {
	oauthResult :=domain.Oauth{}
	oauthResult.ID=id
	err:=database.Master().First(&oauthResult).Error
	if err!=nil {
		return nil,err
	}
	return &oauthResult,nil
}


func  (service*OauthService)Search(userName string)*domain.Oauth  {
	//service.DB.Create()
	return nil
}




